iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0

Fun with HTML5 Canvas趣味畫布

先附上練習的成品.有點像小畫家的畫布一樣,但畫筆顏色、粗細、線條要讓使用者控制的話,就要另外寫js去處理囉~

https://ithelp.ithome.com.tw/upload/images/20240918/201691744IDjOEmh1e.png

附上個人codepen

技巧點

1. canvas

  • 是屬於html的標籤,可以利用js在上面繪圖.本身需要有結尾標籤,有width、height屬性可設置.當然也可以用css去設定寬高、外框邊線、背景之類.這些css設定都不影響畫布的操作.
  • 可以設定id值,方便接下來用js取得dom元素進行操作.
<canvas id="canavs" width="300" height="300"></canvas>
  • 接下來就直接以程式碼,邊講解他的基本繪圖.更詳細的部分MDN文件有教學可以看哈哈.
const canvas = document.querySelector("#canavs");
// 取canvas元素

let isDrawing = false;
// 去判斷使用者開始畫圖了嗎,有開始畫圖才執行畫的動作

let lastX = 0;
let lastY = 0;
// 設定好使用者在畫布上開始要畫圖的起始座標位置,接者才能使畫筆從設定的位置開始.這個位置會根據使用者的操作,去不斷更新位置.不會一直都是(0, 0);

let penColor = 0;
// 畫筆的顏色初始值,因為是採用hsl去變化顏色,不更動飽和度和亮度的狀況下,數值介於0~360之間.

let penDirection = true;
// 控制畫筆粗細的變化,當畫筆愈變愈粗的時候,就改成變細;反之,畫筆變得愈來愈細,就轉換成愈變愈粗.

const ctx = canvas.getContext("2d");
// canvas畫布是空白的,要用getContext()方法取得渲染環境、繪圖函數.getContext()參數可以帶入渲染環境類型,這邊示範的是2d環境.

function draw(e) {
  if (!isDrawing) return;
  // 還沒開始畫畫,就停止繼續執行
  
  ctx.strokeStyle = `hsl(${penColor}, 100%, 50%)`;
  // strokeStyle幫線條上顏色,我這邊會動態調整顏色,所以使用變數penColor.如果你不幫他上指定顏色,預設一開始就是黑色!
  
  ctx.lineCap = "round";
  // 設定線條結尾的樣式,有三種樣式:butt、round、square
  
  ctx.lineJoin = "round";
  // 設定線條和線條間接合處的樣式,有三種樣式:bevel、round、miter
  
  ctx.beginPath();
  // 產生一個新路徑來畫圖,有了路徑之後就能以線條或是填滿的方式渲染出來.
  
  ctx.moveTo(lastX, lastY);
  // 指定一開始繪畫的起始位置,這邊就是抓使用者開始畫的位置.
  
  ctx.lineTo(e.offsetX, e.offsetY);
  // 希望將線條(路徑)往哪邊畫過去,是一個x和y座標.一樣抓取使用者的繪圖座標.
  ctx.closePath();
  // 畫完之後,將路徑關閉結束.
  // 但如果你是有畫出封閉的圖型,就可以用fill(),就會關閉,因此closePath不是必要的方法.
  
  ctx.stroke();
  // 因為我是用線條,方法就是用stroke畫筆的方式去渲染.圖型的話就會用fill.
  // 注意,這邊如果忘記用stroke,你會什麼東西都沒有渲染出來!!!
  
  penColor++;
  if (penColor > 360) {
    penColor = 0;
  };
  // 處理畫筆顏色的變化,不能超過hsl的h值360
  
  if (ctx.lineWidth > 20 || ctx.lineWidth <= 1) {
    penDirection = !penDirection;
  }
  if (penDirection) {
    ctx.lineWidth++;
  } else {
    ctx.lineWidth--;
  }
  // 處理畫筆粗細的變化,太粗就變細,太細就變粗
  
  [lastX, lastY] = [e.offsetX, e.offsetY];
  // 記得要更新使用者滑鼠的位置,不然線就會每次都從使用者的起始位置開始畫.
  // 假設使用者一開始的座標是(100,100),然後移動到任意位置,每次移動,線就會從(100,100)開始畫,一直畫到使用者停住滑鼠的座標位置.就會發現這樣繞一圈360度,就會畫出一個圓圈了哈哈
}

function cleanCanvas() {
  ctx.clearRect(0, 0, 500, 500);
}
// 清除整個畫布
// 參數介紹(X座標, Y座標, 想清除的畫布寬度範圍, 想清除的畫布高度範圍)

canvas.addEventListener("mousemove", draw);
// 監聽滑鼠移動就執行畫圖

canvas.addEventListener("mousedown", (e) => {
 isDrawing = true;
 [lastX, lastY] = [e.offsetX, e.offsetY];
});
// 一按下滑鼠,就取得起始的座標位置,並更新是否畫圖中的狀態

canvas.addEventListener("mouseup", () => isDrawing = false);
canvas.addEventListener("mouseout", () => isDrawing = false);
// 滑鼠按完彈起來、離開畫布的範圍時候,去更新是否畫圖中的狀態

心得

canvas是一個滿有趣的東西,可以做一些好炫的動畫效果,但我還是很菜菜的,能夠像小畫家一樣的功能我就滿足了?

有空再研究好了~(就是沒空


上一篇
Array Cardio陣列方法
下一篇
Must know dev tools tricks開發者工具
系列文
鱷魚帶我練習JavaScript之個人練功坊17
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言